﻿namespace Core.Models;

/// <summary>
/// 结果响应的基础接口，定义了成功状态、状态码和消息提示。
/// </summary>
public interface IResult
{
    /// <summary>
    /// 获取结果是否成功的标识。
    /// </summary>
    bool Success { get; set; }

    /// <summary>
    /// 获取或设置状态码。
    /// </summary>
    int Code { get; set; }

    /// <summary>
    /// 获取或设置消息提示。
    /// </summary>
    string Message { get; set; }
}

/// <summary>
/// 泛型结果响应接口，继承自 <see cref="IResult"/>，增加了返回数据的定义。
/// </summary>
/// <typeparam name="T">结果数据的类型。</typeparam>
public interface IResult<out T> : IResult
{
    /// <summary>
    /// 获取返回的数据。
    /// </summary>
    T? Data { get; }
}

/// <summary>
/// 表示一般情况下的结果响应，实现了 <see cref="IResult"/> 接口。
/// </summary>
public class Result : IResult
{
    internal Result()
    {
    }

    /// <summary>
    /// 使用指定的成功标识和错误消息集合初始化 <see cref="Result"/> 类的新实例。
    /// </summary>
    /// <param name="success">操作是否成功。</param>
    /// <param name="errors">错误消息集合。</param>
    internal Result(bool success, IEnumerable<string>? errors)
    {
        Success = success;
        Message = errors != null && errors.Any() ? string.Join(";", errors) : "操作成功";
    }

    /// <inheritdoc/>
    public bool Success { get; set; }

    /// <inheritdoc/>
    public int Code { get; set; } = 200;

    /// <inheritdoc/>
    public string Message { get; set; } = "操作成功";

    /// <summary>
    /// 创建一个成功的 <see cref="Result"/> 实例。
    /// </summary>
    /// <returns>成功的结果。</returns>
    public static Result Succeed() => new Result(true, new string[] { "操作成功" });

    /// <summary>
    /// 异步方式创建一个成功的 <see cref="Result"/> 实例。
    /// </summary>
    /// <returns>成功的结果的任务。</returns>
    public static Task<Result> SucceedAsync() => Task.FromResult(Succeed());

    /// <summary>
    /// 使用指定的错误消息集合创建一个失败的 <see cref="Result"/> 实例。
    /// </summary>
    /// <param name="errors">错误消息集合。</param>
    /// <returns>失败的结果。</returns>
    public static Result Failure(IEnumerable<string> errors) => new Result(false, errors);

    /// <summary>
    /// 异步方式使用指定的错误消息集合创建一个失败的 <see cref="Result"/> 实例。
    /// </summary>
    /// <param name="errors">错误消息集合。</param>
    /// <returns>失败的结果的任务。</returns>
    public static Task<Result> FailureAsync(IEnumerable<string> errors) => Task.FromResult(Failure(errors));
}

/// <summary>
/// 泛型结果响应，继承自 <see cref="Result"/>，实现了 <see cref="IResult{T}"/> 接口。
/// </summary>
/// <typeparam name="T">结果数据的类型。</typeparam>
public class Result<T> : Result, IResult<T>
{
    /// <summary>
    /// 获取或设置返回的数据。
    /// </summary>
    public T? Data { get; set; }

    /// <summary>
    /// 使用指定的错误消息集合创建一个失败的 <see cref="Result{T}"/> 实例。
    /// </summary>
    /// <param name="errors">错误消息集合。</param>
    /// <returns>失败的结果。</returns>
    public static new Result<T> Failure(IEnumerable<string> errors) =>
        new Result<T> { Code = 400, Success = false, Message = string.Join(";", errors) };

    /// <summary>
    /// 异步方式使用指定的错误消息集合创建一个失败的 <see cref="Result{T}"/> 实例。
    /// </summary>
    /// <param name="errors">错误消息集合。</param>
    /// <returns>失败的结果的任务。</returns>
    public static new async Task<Result<T>> FailureAsync(IEnumerable<string> errors) =>
        await Task.FromResult(Failure(errors));

    /// <summary>
    /// 使用指定的数据创建一个成功的 <see cref="Result{T}"/> 实例。
    /// </summary>
    /// <param name="data">结果数据。</param>
    /// <returns>成功的结果。</returns>
    public static Result<T> Succeed(T data) => new Result<T> { Success = true, Data = data };

    /// <summary>
    /// 使用指定的成功标识、数据和错误消息集合创建一个 <see cref="Result{T}"/> 实例。
    /// </summary>
    /// <param name="success">操作是否成功。</param>
    /// <param name="data">结果数据。</param>
    /// <param name="errorsForFailure">错误消息集合（仅在失败时有效）。</param>
    /// <returns>结果。</returns>
    public static Result<T> Succeed(bool success, T data, IEnumerable<string> errorsForFailure) =>
        success ? new Result<T> { Success = true, Data = data } : Failure(errorsForFailure);

    /// <summary>
    /// 异步方式使用指定的数据创建一个成功的 <see cref="Result{T}"/> 实例。
    /// </summary>
    /// <param name="data">结果数据。</param>
    /// <returns>成功的结果的任务。</returns>
    public static async Task<Result<T>> SucceedAsync(T data) => await Task.FromResult(Succeed(data));

    /// <summary>
    /// 异步方式使用指定的成功标识、数据和错误消息集合创建一个 <see cref="Result{T}"/> 实例。
    /// </summary>
    /// <param name="success">操作是否成功。</param>
    /// <param name="data">结果数据。</param>
    /// <param name="errorsForFailure">错误消息集合（仅在失败时有效）。</param>
    /// <returns>结果的任务。</returns>
    public static async Task<Result<T>> SucceedAsync(bool success, T data, IEnumerable<string> errorsForFailure) =>
        success ? await Task.FromResult(Succeed(data)) : await Task.FromResult(Failure(errorsForFailure));
}
